import { _decorator, Component, Node, Input, input, EventTouch, tween, Vec3, Tween, Director, Label, ParticleSystem2D, Sprite } from 'cc';
const { ccclass, property } = _decorator;

@ccclass('Game')
export class Game extends Component {
  // null! 非空断言"，意思是你确定这个变量在后面的代码中不会是null或者undefined
  @property({ type: Node })
  private bulletNode: Node = null!; // 子弹节点

  @property({ type: Node })
  private enemyNode: Node = null!; // 敌人节点

  @property({ type: Label })
  private scoreLabel: Label = null!; // 得分label

  @property({ type: Node })
  private boomNode: Node = null!; // 粒子节点

  // 缓动对象
  private bulletTween: Tween<Node> = null!; // 子弹节点缓动对象
  private enemyTween: Tween<Node> = null!; // 敌人节点的缓动对象

  // 子弹是否发射标识
  private isFired: Boolean = false;

  // 游戏状态
  private gameState: Number = 0; // 游戏状态 [1-开始 2-结束]

  private score: number = 0; // 得分

  onLoad() {
    //   input 对象 监听回调函数是 fire函数
    input.on(Input.EventType.TOUCH_START, this.handleFire, this);
  }
  start() {
    this.setLevel(true);
  }

  update(deltaTime: number) {
    this.checkHit();
  }

  onDestroy() {
    input.off(Input.EventType.TOUCH_START, this.handleFire, this);
  }

  // ** ---------- 初始化 ---------- **
  // 关卡设置
  setLevel(isInit = false) {
    // 敌人初始化
    this.enemyInit();

    // 子弹初始化
    this.bulletInit();

    this.isFired = false;
    if (isInit) {
      this.gameState = 1;
      //   重置得分
      this.setScore(true);
    }
  }

  // 敌人初始化
  enemyInit() {
    let start_pos = new Vec3(300, 260, 0); // 敌人初始化位置
    start_pos.y = start_pos.y - Math.random() * 60; // 初始y的坐标位置[200~260]
    console.log("🚀🚀 ~ Game ~ enemyInit ~ start_pos:", start_pos)

    let duration = 1.5 - Math.random() * 0.5; // 敌人动画持续时间 1~1.5

    // 初始位置x坐标改变 - 50%
    if (Math.random() > 0.5) {
      start_pos.x = -start_pos.x;
    }

    this.enemyNode.setPosition(start_pos); // 设置敌人开始位置

    this.enemyNode.active = true; // 敌人可见

    // 指定敌人缓动对象和动画【注意坐标系】
    const animation1 = { position: new Vec3(-start_pos.x, start_pos.y, 0) };
    const animation2 = { position: new Vec3(start_pos.x, start_pos.y, 0) };

    // 让敌人重复从左到右，再从右到左的动画 【union()聚合所有动画成一个】
    this.enemyTween = tween(this.enemyNode).to(duration, animation1).to(duration, animation2).union().repeatForever().start();
  }

  // 子弹初始化
  bulletInit() {
    let start_pos = new Vec3(0, -340, 0);
    this.bulletNode.setPosition(start_pos); // 设置子弹位置
    this.bulletNode.active = true; // 子弹节点显示
  }

  // ** ---------- 初始化 End---------- **

  // 业务
  handleFire() {
    console.log(this.isFired, 'handleFire');
    if (this.isFired) {
      // 已经发射，则停止
      return false;
    }
    this.isFired = true; // 第一次发射后改变状态

    // 指定缓动对象
    // 使用缓动系统的to属性，让子弹节点在固定时间内移动到指定坐标
    // 0.6s移动到y600的位置
    this.bulletTween = tween(this.bulletNode)
      .to(0.6, { position: new Vec3(0, 600, 0) })
      .call(() => {
        // 如果到达了y-600的位置，说明游戏结束【能到600说明没打到敌人】
        this.gameOver();
      })
      .start();
  }

  // 检测子弹和敌人的位置，当子弹bullet节点和enemy节点的距离小于一个值作为碰撞界限【因为功能简易，从而不引入碰撞系统】
  checkHit() {
    // 子弹发射后才执行逻辑
    if (!this.isFired) return false;

    // 获取两个需要碰撞的节点距离
    let distance = Vec3.distance(this.bulletNode.position, this.enemyNode.position);
    const HIT_LIMIT = 50; // 碰撞界限

    if (distance <= HIT_LIMIT) {
      // 关闭 子弹的缓动动画
      this.bulletTween.stop(); // 关闭
      this.enemyTween.stop();

      this.gameState = 2; // 游戏结束

      //   播放粒子特效
      let enemyColor = this.enemyNode.getComponent(Sprite).color; // 获取敌人节点上精灵图组件的颜色
      this.boom(this.bulletNode.position, enemyColor);

      // 隐藏子弹和敌人
      this.bulletNode.active = false;
      this.enemyNode.active = false;
      this.setScore(); // 设置得分
      this.setLevel(); // 新关卡
    }
  }

  //   粒子爆炸效果
  boom(pos: any, color: any) {
    // 设置爆炸的位置
    this.boomNode.setPosition(pos);
    // 获取boomNode节点中2D粒子组件
    let particle = this.boomNode.getComponent(ParticleSystem2D);
    // 设置爆炸粒子的颜色
    if (!color) {
      particle.startColor = particle.endColor = color;
    }
    // 杀死所有存在的粒子，然后重新启动粒子发射器
    particle.resetSystem();
  }

  // 得分设置
  setScore(isReset = false) {
    isReset ? (this.score = 0) : (this.score += 1);
    this.scoreLabel.string = this.score.toString();
  }

  // 游戏结束
  gameOver() {
    this.gameState = 2;

    // 播放死亡粒子效果
    let bulletColor = this.bulletNode.getComponent(Sprite).color; // 获取子弹的颜色
    this.boom(this.bulletNode.position, bulletColor);

    setTimeout(() => {
      Director.instance.loadScene('Game'); // 重新加载Game场景
    }, 1200);
  }
}
